using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using OpenComposite.Base.Designer;
using OpenComposite.EII.Repository;
using System.Drawing.Text;

namespace OpenComposite.EII.Designer
{
	public partial class ToolboxDockContent : DockContent, OpenComposite.EII.Designer.IRepositoryToolbox
	{
		#region Initialization
		public ToolboxDockContent()
		{
			InitializeComponent();

			init();
		}
		private void init()
		{
			if ( this.DesignMode )
				return;

			this.DoubleBuffered = true;
			this.ShowHint = DockState.DockLeftAutoHide;
			this.Icon = global::OpenComposite.Repository.Properties.Resources.ico_toolbox_16;
			//if ( Application.RenderWithVisualStyles ) {
			//    this.lbToolbox.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
			//} else {
			//    this.lbToolbox.BorderStyle = System.Windows.Forms.BorderStyle.None;
			//}
		}
		#endregion

		#region Variables
		private InternalToolboxItem _currentSelection = null;
		#endregion

		#region Properties
		public ListBox Toolbox
		{
			get { return lbToolbox; }
		}
		#endregion

		#region Methods
		public void AddItem(ItemType type, string category)
		{
			this.lbToolbox.Items.Add(new InternalToolboxItem(type));
		}
		public void AddItem(ItemType typeDiagram, ItemType type, string category)
		{
			this.lbToolbox.Items.Add(new InternalToolboxItem(typeDiagram, type));
		}

		public void Clear()
		{
			this.lbToolbox.Items.Clear();
		}
		public void Clear(string category)
		{
			this.lbToolbox.Items.Clear();
		}

		#endregion

		#region Event Handler
		private void lbToolbox_SelectedIndexChanged(object sender, EventArgs e)
		{
			InternalToolboxItem toolboxItem = lbToolbox.SelectedItem as InternalToolboxItem;
			if ( toolboxItem != null &&
				 toolboxItem.Type != ItemType.Undefined && toolboxItem.Type != ItemType.Separator ) {
				_currentSelection = toolboxItem;
			} else if ( _currentSelection != null ) {
				lbToolbox.SelectedItem = _currentSelection;
			}
		}

		private void lbToolbox_DoubleClick(object sender, EventArgs e)
		{

		}

		private void lbToolbox_MouseMove(object sender, MouseEventArgs e)
		{
			if ( e.Button == MouseButtons.Left && this.lbToolbox.SelectedItem != null ) {
				InternalToolboxItem selectedItem = lbToolbox.SelectedItem as InternalToolboxItem;

				if ( selectedItem == null ||
					 selectedItem.Type == ItemType.Separator || selectedItem.Type == ItemType.Undefined )
					return;

				DragDropEffects effects = DoDragDrop(selectedItem.Type,
													 DragDropEffects.Copy | DragDropEffects.Move);
			} else if ( e.Button == MouseButtons.None ) {

			}
		}

		private void lbToolbox_DrawItem(object sender, DrawItemEventArgs e)
		{
			if ( e.Index < 0 )
				return;

			Graphics g = e.Graphics;
			ListBox listBox = (ListBox)sender;
			object objItem = e.Index >= 0 && e.Index < listBox.Items.Count ? listBox.Items[e.Index] : null;
			InternalToolboxItem item = null;
			Bitmap bitmap = null;
			string text = null;

			if ( objItem is string ) {
				bitmap = null;
				text = (string)objItem;
			} else {
				item = (InternalToolboxItem)objItem;
				bitmap = (Bitmap)item.Image; // if it's not a bitmap, it's a metafile, and how likely is that?
				text = item.Name;
			}
			if ( item != null && item.Type == ItemType.Separator ) {
				int y = e.Bounds.Y + (int)( e.Bounds.Height / 2 );
				g.DrawLine(SystemPens.ControlDarkDark, e.Bounds.Left, y, e.Bounds.Right, y);
			} else {
				bool selected = false;
				bool disabled = false;
				//bool hottrack = lbToolbox.IndexFromPoint(lbToolbox.PointToClient(Cursor.Position)) == e.Index;

				if ( ( e.State & DrawItemState.Selected ) == DrawItemState.Selected )
					selected = true;

				if ( (int)( e.State & ( DrawItemState.Disabled | DrawItemState.Grayed | DrawItemState.Inactive ) ) != 0 )
					disabled = true;

				StringFormat format = new StringFormat();
				format.HotkeyPrefix = HotkeyPrefix.Show;
				format.Trimming = StringTrimming.EllipsisCharacter;

				int x = e.Bounds.X + 4;
				x += 20;

				if ( selected ) {
					Rectangle r = e.Bounds;
					r.Width--; r.Height--;
					g.DrawRectangle(SystemPens.ActiveCaption, r);
				} else {
					//Brush bgBrush = ( hottrack ) ? new SolidBrush(Color.FromArgb(120, SystemColors.HotTrack)) : SystemBrushes.Control;
					g.FillRectangle(SystemBrushes.Control, e.Bounds);
					//if ( hottrack )
					//    bgBrush.Dispose();

					//using ( Brush border = new SolidBrush(Color.FromArgb(Math.Min(SystemColors.Control.R + 15, 255), Math.Min(SystemColors.Control.G + 15, 255), Math.Min(SystemColors.Control.B + 15, 255))) )
					//    g.FillRectangle(border, new Rectangle(e.Bounds.X, e.Bounds.Y, 20, e.Bounds.Height));
				}

				if ( bitmap != null )
					g.DrawImage(bitmap, e.Bounds.X + 2, e.Bounds.Y + 2, 16, 16);

				Brush textBrush = ( disabled ) ? new SolidBrush(Color.FromArgb(120, SystemColors.ControlText)) : SystemBrushes.FromSystemColor(SystemColors.ControlText);
				RectangleF rfText = new RectangleF(x, e.Bounds.Y + 2, e.Bounds.Width - x - 2, e.Bounds.Height - 4);
				g.DrawString(text, lbToolbox.Font, textBrush, rfText, format);
				if ( disabled )
					textBrush.Dispose();
				format.Dispose();
			}
		}

		private void lbToolbox_KeyPress(object sender, KeyPressEventArgs e)
		{

		}

		private void toolTip1_Popup(object sender, PopupEventArgs e)
		{
			if ( e.AssociatedControl == lbToolbox ) {
				int index = lbToolbox.IndexFromPoint(lbToolbox.PointToClient(Cursor.Position));
				InternalToolboxItem item = lbToolbox.Items[index] as InternalToolboxItem;
				if ( item != null && item.Type != ItemType.Separator && item.Type != ItemType.Undefined ) {
					e.ToolTipSize = TextRenderer.MeasureText(item.ToolTip, lbToolbox.Font);
				}
			}
		}

		private void toolTip1_Draw(object sender, DrawToolTipEventArgs e)
		{
			if ( e.AssociatedControl == lbToolbox ) {
				e.DrawBackground();
				e.DrawBorder();
				int index = lbToolbox.IndexFromPoint(lbToolbox.PointToClient(Cursor.Position));
				InternalToolboxItem item = lbToolbox.Items[index] as InternalToolboxItem;
				if ( item != null && item.Type != ItemType.Separator && item.Type != ItemType.Undefined ) {
					// Draw the custom text.
					// The using block will dispose the StringFormat automatically.
					using ( StringFormat sf = new StringFormat() ) {
						sf.Alignment = StringAlignment.Center;
						sf.LineAlignment = StringAlignment.Center;
						sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.None;
						sf.FormatFlags = StringFormatFlags.NoWrap;
						e.Graphics.DrawString(item.ToolTip, lbToolbox.Font,
							SystemBrushes.InfoText, e.Bounds, sf);
					}
				} else {
					e.DrawText();
				}
			} else {
				e.DrawBackground();
				e.DrawBorder();
				e.DrawText();
			}

		}

		#endregion
	}
	#region Class: ToolboxItem
	internal class InternalToolboxItem
	{
		private ItemType _typeDiagram = ItemType.Undefined;
		private ItemType _type = ItemType.Undefined;
		private string _name = "";
		private string _tooltip = "";
		private Image _img = null;

		public InternalToolboxItem(ItemType type)
		{
			this._type = type;
			if ( type != ItemType.Separator ) {
				if ( !RepositoryService.GetToolboxInfos(_typeDiagram, _type, out _img, out _name, out _tooltip) )
					throw new Exception("Undefined Toolbox Item.");
			}
		}
		public InternalToolboxItem(ItemType typeDiagram, ItemType type)
		{
			this._typeDiagram = typeDiagram;
			this._type = type;
			if ( _type != ItemType.Separator ) {
				if ( !RepositoryService.GetToolboxInfos(_typeDiagram, _type, out _img, out _name, out _tooltip) )
					throw new Exception("Undefined Toolbox Item.");
			}
		}

		public ItemType Type
		{
			get { return _type; }
		}

		public string Name
		{
			get { return _name; }
		}
		public string ToolTip
		{
			get { return _tooltip; }
		}
		public virtual Image Image
		{
			get { return _img; }
		}

		public override string ToString()
		{
			return this.Name;
		}
	}
	#endregion


}